home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CreatingGames / Utilities / Misc / ModemLink / Source / Modem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-24  |  9.2 KB  |  375 lines

  1. /*
  2. ** NAME: Modem.c
  3. ** DESC: routines to use the modem to dial/answer or any other modem command.
  4. **
  5. ** AUTHOR:        DATE:       DESCRIPTION:
  6. ** ~~~~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  7. ** Mike Veroukis  06 Apr 1997 Created
  8. ** Mike Veroukis  24 Oct 1997 re-worked SendModemCMD so that it now checks if
  9. **                            modem is off only after it doesn't get a response
  10. **                            from the modem.  Aso re-worked SendModemCMD to
  11. **                            be more flexible and reduce the chance that it
  12. **                            will confuse itself.  Changed the default Suffix
  13. **                            tag to "\r" instead of "\n\r", and also made
  14. **                            sure the modem commands return more meaningful
  15. **                            error/return codes (according to docs).
  16. */
  17.  
  18.  
  19. #include <exec/types.h>
  20. #include <exec/memory.h>
  21. #include <exec/io.h>
  22. #include <exec/ports.h>
  23. #include <devices/serial.h>
  24. #include <devices/timer.h>
  25. #include <dos/dosextens.h>
  26. #include <dos/dostags.h>
  27. #include <utility/tagitem.h>
  28.  
  29. #include <proto/dos.h>
  30. #include <proto/exec.h>
  31. #include <proto/utility.h>
  32.  
  33. #include <string.h>
  34. #include <stdio.h>
  35.  
  36. #include "Modem.h"
  37. #include "ModemLinkAPI.h"
  38. #include "DeviceStuff.h"
  39. #include "ModemLinkTask.h"
  40.  
  41.  
  42. /*
  43. ** These are bits used by the serial device (via io_Status)
  44. ** They are used to determine if the modem is on, or if we've connected
  45. */
  46. #define DSR    (1 << 3)
  47. #define CD     (1 << 5)
  48.  
  49.  
  50. /*
  51. ** This is a structure which holds all user configurable settings for
  52. ** the modem realated routines.
  53. */
  54. struct Config {
  55.   int DialTime;
  56.   int AnswerTime;
  57.   char *DialPrefix;
  58.   char *Suffix;
  59.   char *OkText;
  60.   char *BusyText;
  61.   char *NoCarrierText;
  62.   char *NoDialText;
  63.   char *AutoAnsText;
  64. };
  65.  
  66. struct Config StdConfig = {
  67.   45,
  68.   30,
  69.   "ATDT ",
  70.   "\r",
  71.   "OK",
  72.   "BUSY",
  73.   "NO CARRIER",
  74.   "NO DIALTONE",
  75.   "ATS0=1"
  76. };
  77.  
  78.  
  79. /*
  80. ** Prototypes
  81. */
  82. ULONG ML_SendModemCMD(struct IOExtSer *SerIO, char *CMD, struct Config *cfg);
  83.  
  84.  
  85. ///////////////////////////////////////////////////////////////////////////////
  86.  
  87.  
  88. void SetConfig(struct Config *cfg, struct TagItem *tagList)
  89. {
  90.   struct TagItem *tstate;
  91.   struct TagItem *tag;
  92.   ULONG tidata;
  93.  
  94.   *cfg = StdConfig;
  95.  
  96.   tstate = tagList;
  97.  
  98.   while (tag = NextTagItem(&tstate)) {
  99.     tidata = tag->ti_Data;
  100.  
  101.     switch (tag->ti_Tag) {
  102.       case ML_DialTime:
  103.         cfg->DialTime = (int)tidata;
  104.         break;
  105.       case ML_AnswerTime:
  106.         cfg->AnswerTime = (int)tidata;
  107.         break;
  108.       case ML_DialPrefix:
  109.         cfg->DialPrefix = (char *)tidata;
  110.         break;
  111.       case ML_Suffix:
  112.         cfg->Suffix = (char *)tidata;
  113.         break;
  114.       case ML_OkText:
  115.         cfg->OkText = (char *)tidata;
  116.         break;
  117.       case ML_BusyText:
  118.         cfg->BusyText = (char *)tidata;
  119.         break;
  120.       case ML_NoCarrierText:
  121.         cfg->NoCarrierText = (char *)tidata;
  122.         break;
  123.       case ML_NoDialText:
  124.         cfg->NoDialText = (char *)tidata;
  125.         break;
  126.       case ML_AutoAnsText:
  127.         cfg->AutoAnsText = (char *)tidata;
  128.         break;
  129.     }
  130.   }
  131. }
  132.  
  133. ULONG __saveds __asm
  134. ML_SendModemCMDTagList
  135. (
  136.   register __a0 struct IOExtSer *SerIO,
  137.   register __a1 char *CMD,
  138.   register __a2 struct TagItem *tagList
  139. )
  140. {
  141.   struct Config ModemConfig;
  142.  
  143.   if (SerIO && CMD) {
  144.     SetConfig(&ModemConfig, tagList);
  145.     return (ML_SendModemCMD(SerIO, CMD, &ModemConfig));
  146.   }
  147.   return 0L;
  148. }
  149.  
  150. ULONG ML_SendModemCMD(struct IOExtSer *SerIO, char *CMD, struct Config *cfg)
  151. {
  152.   ULONG buf_size;
  153.   int i;
  154.   ULONG ReturnCode = MODEM_NOCARRIER;
  155.   char *buf, b;
  156.  
  157.   if (!cfg)
  158.     cfg = &StdConfig;
  159.  
  160.   buf_size = strlen(CMD) + 16L;
  161.  
  162.   SerIO->IOSer.io_Command = SDCMD_QUERY;
  163.   DoIO((struct IORequest *) SerIO);
  164.  
  165.   if (buf = (char *)AllocMem(buf_size, MEMF_CLEAR)) {
  166.     strcpy(buf, CMD);
  167.     if (cfg->Suffix)
  168.       strcat(buf, cfg->Suffix);
  169.  
  170.     SerIO->IOSer.io_Command = CMD_WRITE;
  171.     SerIO->IOSer.io_Length = strlen(buf);
  172.     SerIO->IOSer.io_Data = (APTR)buf;
  173.     TimedIO((struct IORequest *) SerIO, 2);
  174.  
  175.     SerIO->IOSer.io_Command = CMD_READ;
  176.     SerIO->IOSer.io_Length = 1L;
  177.     SerIO->IOSer.io_Data = (APTR)&b;
  178.  
  179.     if (!TimedIO((struct IORequest *) SerIO, 1))
  180.       ReturnCode = MODEM_ERROR;
  181.  
  182.     if (ReturnCode != MODEM_ERROR) {
  183.       i = 0;
  184.  
  185.       while (ReturnCode == MODEM_NOCARRIER) {
  186.  
  187.         SerIO->IOSer.io_Command = CMD_READ;
  188.         SerIO->IOSer.io_Length = 1;
  189.         SerIO->IOSer.io_Data = (APTR)&b;
  190.  
  191.         if (TimedIO((struct IORequest *) SerIO, cfg->DialTime)) {
  192.           if (b < ' ') {
  193.             buf[i] = 0;
  194.             if (0 == stricmp(buf, cfg->OkText))
  195.               ReturnCode = MODEM_OK;
  196.             else if  (0 == stricmp(buf, cfg->BusyText))
  197.               ReturnCode = MODEM_BUSY;
  198.             else if  (0 == stricmp(buf, cfg->NoCarrierText))
  199.               ReturnCode = MODEM_NOCARRIER;
  200.             else if  (0 == stricmp(buf, cfg->NoDialText))
  201.               ReturnCode = MODEM_NODIAL;
  202.  
  203.             SerIO->IOSer.io_Command = SDCMD_QUERY;
  204.             DoIO((struct IORequest *) SerIO);
  205.  
  206.             if (!(SerIO->io_Status & CD))
  207.               ReturnCode = MODEM_CONNECT;
  208.  
  209.             i = 0;
  210.           }
  211.           else if (i < buf_size-1)
  212.             buf[i++] = b;
  213.         }
  214.         else
  215.           ReturnCode = MODEM_TIMEOUT;
  216.       }
  217.     }
  218.     else if (SerIO->io_Status & DSR)
  219.       ReturnCode = MODEM_OFF;
  220.  
  221.     if (ReturnCode == MODEM_TIMEOUT) {
  222.       strcpy(buf, cfg->Suffix);
  223.       SerIO->IOSer.io_Command = CMD_WRITE;
  224.       SerIO->IOSer.io_Length = strlen(cfg->Suffix);
  225.       SerIO->IOSer.io_Data = (APTR)buf;
  226.       DoIO((struct IORequest *) SerIO);
  227.  
  228.       SerIO->IOSer.io_Command = CMD_READ;
  229.       SerIO->IOSer.io_Length = strlen(cfg->Suffix);
  230.       SerIO->IOSer.io_Data = (APTR)buf;
  231.       TimedIO((struct IORequest *) SerIO, 1);
  232.     }
  233.  
  234.  
  235.     if (ReturnCode != MODEM_OFF) {
  236.       SerIO->IOSer.io_Command = SDCMD_QUERY;
  237.       DoIO((struct IORequest *) SerIO);
  238.  
  239.       if (!(SerIO->io_Status & CD))
  240.         ReturnCode = MODEM_CONNECT;
  241.  
  242.       SerIO->IOSer.io_Command = CMD_CLEAR;
  243.       DoIO((struct IORequest *) SerIO);
  244.     }
  245.  
  246.     FreeMem(buf, buf_size);
  247.   }
  248.  
  249.   return (ReturnCode);
  250. }
  251.  
  252. ULONG __saveds __asm
  253. ML_DialTagList
  254. (
  255.   register __a0 struct IOExtSer *SerIO,
  256.   register __a1 char *PhoneNum,
  257.   register __a2 struct TagItem *tagList
  258. )
  259. {
  260.   struct Config DialConfig;
  261.   char buf[80];
  262.   ULONG ReturnCode = MODEM_ERROR;
  263.  
  264.   SerIO->IOSer.io_Command = SDCMD_QUERY;
  265.   DoIO((struct IORequest *) SerIO);
  266.  
  267.   if (!(SerIO->io_Status & CD))
  268.     ReturnCode = MODEM_CONNECT;
  269.  
  270.   if ((ReturnCode != MODEM_CONNECT) && SerIO && PhoneNum) {
  271.     SetConfig(&DialConfig, tagList);
  272.     strcpy(buf, DialConfig.DialPrefix);
  273.     strcat(buf, PhoneNum);
  274.  
  275.     ReturnCode = ML_SendModemCMD(SerIO, buf, &DialConfig);
  276.   }
  277.  
  278.   return (ReturnCode);
  279. }
  280.  
  281. ULONG __saveds __asm
  282. ML_AnswerTagList
  283. (
  284.   register __a0 struct IOExtSer *SerIO,
  285.   register __a1 struct TagItem *tagList
  286. )
  287. {
  288.   struct Config AnswerConfig;
  289.   struct timerequest *TimerIO = NULL;
  290.   struct MsgPort *TimerMP = NULL;
  291.   ULONG SerBit, TimerBit;
  292.   ULONG booga;
  293.   ULONG ReturnCode = MODEM_TIMEOUT;
  294.   char buf[80];
  295.  
  296.   SerIO->IOSer.io_Command = SDCMD_QUERY;
  297.   DoIO((struct IORequest *) SerIO);
  298.  
  299.   if (!(SerIO->io_Status & CD))
  300.     ReturnCode = MODEM_CONNECT;
  301.  
  302.   if ((ReturnCode != MODEM_CONNECT) && SerIO) {
  303.     if (OpenTimerDevice(&TimerMP, &TimerIO)) {
  304.       SerBit = 1 << SerIO->IOSer.io_Message.mn_ReplyPort->mp_SigBit;
  305.       TimerBit = 1 << TimerMP->mp_SigBit;
  306.  
  307.       SetConfig(&AnswerConfig, tagList);
  308.  
  309.       strcpy(buf, AnswerConfig.AutoAnsText);
  310.       booga = ML_SendModemCMD(SerIO, buf, &AnswerConfig);
  311.  
  312.       if (booga == MODEM_OK) {
  313.         /* Wait for first RING to come in from modem */
  314.         SerIO->IOSer.io_Command = CMD_READ;
  315.         SerIO->IOSer.io_Length = 1;
  316.         SerIO->IOSer.io_Data = (APTR)buf;
  317.         SendIO((struct IORequest *) SerIO);
  318.  
  319.         TimerIO->tr_node.io_Command = TR_ADDREQUEST;
  320.         TimerIO->tr_time.tv_secs = AnswerConfig.AnswerTime;
  321.         TimerIO->tr_time.tv_micro = 0;
  322.         SendIO((struct IORequest *) TimerIO);
  323.  
  324.         while (1) {
  325.           Wait(SerBit | TimerBit);
  326.  
  327.           if (CheckIO((struct IORequest *)SerIO)) {
  328.             WaitIO((struct IORequest *)SerIO);
  329.  
  330.             SerIO->IOSer.io_Command = SDCMD_QUERY;
  331.             DoIO((struct IORequest *) SerIO);
  332.  
  333.             if (!(SerIO->io_Status & CD)) {
  334.               if (!CheckIO((struct IORequest *)TimerIO))
  335.                 AbortIO((struct IORequest *)TimerIO);
  336.               WaitIO((struct IORequest *)TimerIO);
  337.               break;
  338.             }
  339.  
  340.             SerIO->IOSer.io_Command = CMD_READ;
  341.             SerIO->IOSer.io_Length = 1;
  342.             SerIO->IOSer.io_Data = (APTR)buf;
  343.             SendIO((struct IORequest *) SerIO);
  344.           }
  345.  
  346.           if (CheckIO((struct IORequest *)TimerIO)) {
  347.             WaitIO((struct IORequest *)TimerIO);
  348.  
  349.             if (!CheckIO((struct IORequest *)SerIO))
  350.               AbortIO((struct IORequest *)SerIO);
  351.             WaitIO((struct IORequest *)SerIO);
  352.             break;
  353.           }
  354.         }
  355.       }
  356.       else
  357.         ReturnCode = booga;
  358.  
  359.       SafeCloseDevice(TimerMP, (struct IORequest *)TimerIO);
  360.     }
  361.  
  362.     SerIO->IOSer.io_Command = SDCMD_QUERY;
  363.     DoIO((struct IORequest *) SerIO);
  364.  
  365.     if (!(SerIO->io_Status & CD))
  366.       ReturnCode = MODEM_CONNECT;
  367.  
  368.     Delay(10);
  369.     SerIO->IOSer.io_Command = CMD_CLEAR;
  370.     DoIO((struct IORequest *) SerIO);
  371.   }
  372.  
  373.   return (ReturnCode);
  374. }
  375.